﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unis.Framework.Core.Utility;
using Unis.Framework.ORM.Common;
using Unis.Framework.ORM.Model;
using Unis.RuleBase.Common;

namespace Unis.Framework.RuleBase.Common
{
    [Serializable]
    public class ObjectDataList : Dictionary<string, ObjectDataInfo>
    {
        // Fields
        private string[] _ExcludeDataStateChanged = new string[] { "DataRow" };
        private static readonly string ACCEPT_CHANGES_METHOD = "AcceptChanges";
        private static readonly string REJECT_CHANGES_METHOD = "RejectChanges";
        private static readonly string SPE_CHAR = " _~!_M_ ";

        // Methods
        public void AcceptDataChanges()
        {
            foreach (ObjectDataInfo info in this.getCanChanges())
            {
                info.DataState = ObjectDataState.Unchanged;
                this.setObjectAcceptChanges(info.ObjectData);
            }
        }

        public ObjectDataInfo Add(ObjectDataInfo dataInfo)
        {
            dataInfo.SaveToCacheDateTime = DateTime.Now;
            string key = this.toSaveKeyString(dataInfo);
            if (!base.ContainsKey(key))
            {
                base.Add(key, dataInfo);
                return dataInfo;
            }
            base[key] = dataInfo;
            return dataInfo;
        }

        private IEnumerable<ObjectDataInfo> getCanChanges()
        {
            return (from cc in base.Values
                    where (cc.ObjectData != null) && (Array.IndexOf<string>(this._ExcludeDataStateChanged, cc.ObjectData.GetType().Name) >= 0)
                    select cc);
        }

        public IEnumerable<ObjectDataInfo> GetCanSaveAndOrder()
        {
            return (from cc in base.Values
                    where (cc.DataState != ObjectDataState.Detached) && (cc.DataState != ObjectDataState.Unchanged)
                    orderby cc.SaveToCacheDateTime
                    orderby cc.SaveOrderIndex
                    select cc);
        }

        public IEnumerable<ObjectDataInfo> OrderBySaveIndex()
        {
            return (from cc in base.Values
                    where cc != null
                    orderby cc.SaveOrderIndex
                    select cc);
        }

        public void RejectDataChanges()
        {
            foreach (ObjectDataInfo info in this.getCanChanges())
            {
                Reflection.InvokeMethodByName(info.ObjectData, REJECT_CHANGES_METHOD, new object[0]);
            }
        }

        private void setObjectAcceptChanges(object data)
        {
            BaseModel model = data as BaseModel;
            if (model != null)
            {
                model.EntityState = EntityState.Persistent;
            }
            else
            {
                IList list = data as IList;
                if (list != null)
                {
                    foreach (object obj2 in list)
                    {
                        this.setObjectAcceptChanges(obj2);
                    }
                }
                else
                {
                    Reflection.InvokeMethodByName(data, ACCEPT_CHANGES_METHOD, new object[0]);
                }
            }
        }

        private string toSaveKeyString(ObjectDataInfo dataInfo)
        {
            string str = dataInfo.GetHashCode().ToString();
            if (dataInfo.DataInDocType != null)
            {
                str = str + " " + dataInfo.DataInDocType.ToString();
            }
            TimeSpan span = dataInfo.SaveToCacheDateTime.Subtract(DateTime.MinValue);
            object obj2 = str;
            return string.Concat(new object[] { obj2, SPE_CHAR, dataInfo.DataState.ToString(), SPE_CHAR, span.TotalMilliseconds });
        }
    }
}
